﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SharpArch.NHibernate;

namespace ADIGRE.Infrastructure.Queries.Contabilidade
{
    public class vwLivroCaixa : NHibernateQuery<Domain.View.vwLivroCaixa>, IvwLivroCaixa
    {
        public override IList<Domain.View.vwLivroCaixa> ExecuteQuery()
        {

            throw new NotImplementedException();
        }

        public List<Domain.View.vwLivroCaixa> GetAll()
        {
            throw new NotImplementedException();
        }

        public Domain.View.vwLivroCaixa Get(DateTime DtReferencia)
        {
            var LivroCaixa = new Domain.View.vwLivroCaixa();
            LivroCaixa.DtPeriodoInicial = DtReferencia;

            //recupera lancamento anterior
            var MesAnterior = Session.QueryOver<Domain.RoutineTable.BalancoMensal>()
                    .WhereRestrictionOn(x => x.DtPeriodo.Value)
                        .IsBetween(LivroCaixa.DtPeriodoInicial.Value.AddDays(-1))
                            .And(LivroCaixa.DtPeriodoInicial.Value.AddMonths(-1))
                    .OrderBy(x => x.DtCadastro).Desc
                    .SingleOrDefault();

            //se não houver lancamento do mes anterior calcula todos os lancamentos anteriores
            if (LivroCaixa.isContabilizado = MesAnterior != null)
                LivroCaixa.VlSaldoAnterior = MesAnterior.VLSaldo;
            else
            {
                var anterior = Session.QueryOver<Domain.Lancamento>().WhereNot(x => x.IsExcluido).And(x => x.DtLancamento < LivroCaixa.DtPeriodoInicial).List();
                decimal oldEntrada = anterior.Where(x => x.IsEntrada).Sum(x => x.VlLancamento);
                decimal oldSaida = anterior.Where(x => !x.IsEntrada).Sum(x => x.VlLancamento);
                LivroCaixa.VlSaldoAnterior = (decimal)(oldEntrada - oldSaida);
            }

            //discrimina lançamento por tipo
            var pagamento = Session.QueryOver<Domain.Pagamento>().WhereNot(x => x.IsExcluido).AndRestrictionOn(x => x.DtLancamento).IsBetween(LivroCaixa.DtPeriodoInicial).And(LivroCaixa.DtPeriodoFinal).List();
            var recibo = Session.QueryOver<Domain.Recibo>().WhereNot(x => x.IsExcluido).AndRestrictionOn(x => x.DtLancamento).IsBetween(LivroCaixa.DtPeriodoInicial).And(LivroCaixa.DtPeriodoFinal).List();
            var oferta = Session.QueryOver<Domain.Oferta>().WhereNot(x => x.IsExcluido).AndRestrictionOn(x => x.DtLancamento).IsBetween(LivroCaixa.DtPeriodoInicial).And(LivroCaixa.DtPeriodoFinal).List();
            var dizimo = Session.QueryOver<Domain.Dizimo>().WhereNot(x => x.IsExcluido).AndRestrictionOn(x => x.DtLancamento).IsBetween(LivroCaixa.DtPeriodoInicial).And(LivroCaixa.DtPeriodoFinal).List();

            //atribui a cada tipo de lancamento o formato devido
            var LivroCaixaP = pagamento
                .Select(x => new Domain.View.vwLancamentoLivroCaixa
                {
                    Id = x.Id,
                    DsHistorico = string.Format("{0} {1}", x.Despesa.NmDespesa, (string.IsNullOrWhiteSpace(x.NuNota)) ? "" : " (Nº Nota / Doc.: " + x.NuNota + ")").Trim(),
                    Responsavel = (x.UsuarioAlterado == null) ? x.UsuarioCadastro : x.UsuarioAlterado,
                    DtLancamento = x.DtLancamento,
                    VlSaida = x.VlLancamento,
                    isEntrada = x.IsEntrada
                }).ToList();

            var LivroCaixaD = dizimo
                .Select(x => new Domain.View.vwLancamentoLivroCaixa
                {
                    Id = x.Id,
                    DsHistorico = string.Format("{0} de {1}", x.EnumLancamento, x.Dizimista.NmPessoa).Trim(),
                    Responsavel = (x.UsuarioAlterado == null) ? x.UsuarioCadastro : x.UsuarioAlterado,
                    DtLancamento = x.DtLancamento,
                    VlEntrada = x.VlLancamento,
                    isEntrada = x.IsEntrada
                }).ToList();

            var LivroCaixaR = recibo
                .Select(x => new Domain.View.vwLancamentoLivroCaixa
                {
                    Id = x.Id,
                    DsHistorico = string.Format("{0} (Recibo Nº{1})", x.Despesa.NmDespesa, x.NuRecibo).Trim(),
                    Responsavel = (x.UsuarioAlterado == null) ? x.UsuarioCadastro : x.UsuarioAlterado,
                    DtLancamento = x.DtLancamento,
                    VlSaida = x.VlLancamento,
                    isEntrada = x.IsEntrada
                }).ToList();

            var LivroCaixaO = oferta
                .Select(x => new Domain.View.vwLancamentoLivroCaixa
                {
                    Id = x.Id,
                    DsHistorico = string.Format("{0}", x.EnumLancamento).Trim(),
                    Responsavel = (x.UsuarioAlterado == null) ? x.UsuarioCadastro : x.UsuarioAlterado,
                    DtLancamento = x.DtLancamento,
                    VlEntrada = x.VlLancamento,
                    isEntrada = x.IsEntrada
                }).ToList();

            //mescla lancamentos ordenando pela data de lancamento
            var ItemLivroCaixa = LivroCaixaD.Union(LivroCaixaO).Union(LivroCaixaP).Union(LivroCaixaR).OrderBy(x => x.DtLancamento);

            //calcula saldo em cada lancamento
            decimal saldo = LivroCaixa.VlSaldoAnterior;
            foreach (var item in ItemLivroCaixa)
            {
                item.VlSaldo = saldo = (item.VlEntrada - item.VlSaida) + saldo;
            }

            //atribui lancamentos ao livro caixa
            LivroCaixa.Lancamentos = ItemLivroCaixa.ToList();
            return LivroCaixa;
        }
    }
}
